<template>
	<div class="pro-upload-img-box">
		<div class="pro-upload-img-content">
			<!-- 上传组件 -->
			<el-upload
				v-loading="loading"
				ref="proUploadImgRef"
				:class="['pro-upload-img', { 'is-disabled': disabled }]"
				v-bind="uploadProps"
				action="#"
				:http-request="importFile"
				:before-upload="beforeUpload"
				:on-success="handleSuccess"
				:on-error="handleError"
				:on-exceed="handleExceed"
			>
				<slot>
					<!-- 已上传图片列表 -->
					<div
						class="upload-img-card"
						v-if="fileList.length > 0"
						v-for="(item, index) in fileList"
						:key="index"
					>
						<el-image
							class="img-sty"
							referrerpolicy="no-referrer"
							fit="cover"
							:src="item.url"
							alt=""
						/>
						<!-- 删除按钮 -->
						<el-image
							v-if="!disabled"
							src="https://static.wxb.com.cn/frontEnd/images/ideacome-vue3-component/img-close.png"
							class="img-close"
							@click.stop="handleRemove(item, index)"
						/>
						<!-- 图片遮罩层 -->
<!--						<div class="img-mask">
							<el-image
								src="https://static.wxb.com.cn/frontEnd/images/ideacome-vue3-component/img-preview.png"
								class="img-preview"
							/>
						</div>-->
					</div>

					<!-- 上传按钮 -->
					<div class="upload-card" v-else>
						<el-icon class="upload-icon">
							<Plus />
						</el-icon>
						<div v-if="uploadText" class="upload-text">
							{{ uploadText }}
						</div>
					</div>
				</slot>
			</el-upload>
		</div>
		<!-- 提示信息 -->
		<slot name="tip">
			<div class="upload-tip" v-if="tip">
				{{ tip }}
			</div>
		</slot>
	</div>
</template>

<script lang="ts" setup>
// 脚本部分保持不变
import { ref, computed } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { uploadBookImage } from '/@/api/file/index';

// Props 定义
const props = defineProps({
	/** 上传地址 */
	action: {
		type: String
	},
	/** 请求头 */
	headers: {
		type: Object,
		default: () => ({}),
	},
	/** 是否支持多选 */
	multiple: {
		type: Boolean,
		default: false,
	},
	/** 最大上传数量，0表示不限制 */
	limit: {
		type: Number,
		default: 0,
	},
	/** 接受的文件类型，如：.jpg,.png,.jpeg */
	accept: {
		type: String,
		default: '.jpg,.png,.jpeg',
	},
	/** 文件大小限制 */
	maxSize: {
		type: Number,
		default: 0,
	},
	/** 文件大小单位（KB/MB） */
	sizeUnit: {
		type: String,
		default: 'MB',
		validator: (value) => ['KB', 'MB'].includes(value),
	},
	/** 图片宽度限制 */
	width: {
		type: Number,
		default: 0,
	},
	/** 图片高度限制 */
	height: {
		type: Number,
		default: 0,
	},
	/** 上传提示文字 */
	uploadText: {
		type: String,
		default: '上传图片',
	},
	/** 上传提示说明 */
	tip: {
		type: String,
		default: '',
	},
	/** 是否禁用 */
	disabled: {
		type: Boolean,
		default: false,
	},
});
/** 初始文件列表 */
const fileList = defineModel('fileList', {
	type: Array,
	default: () => [],
});

// 事件定义
const emit = defineEmits(['success', 'error', 'exceed', 'remove']);

const proUploadImgRef = ref();
const loading = ref(false);

const uploadProps = computed(() => ({
	action: props.action,
	accept: props.accept,
	limit: props.limit,
	multiple: props.multiple,
	listType: 'picture-card',
	showFileList: false,
	headers: props.headers,
	fileList: fileList.value,
	disabled: props.disabled,
}));

/**
 * 验证图片尺寸是否符合要求
 * @param {number} width - 图片宽度
 * @param {number} height - 图片高度
 * @returns {boolean} 是否符合要求
 */
const validateImageSize = (width, height) => {
	if (props.width && props.height) {
		return width === props.width && height === props.height;
	}
	if (props.width) {
		return width === props.width;
	}
	if (props.height) {
		return height === props.height;
	}
	return true;
};

/**
 * 上传前校验
 * @param {File} file - 待上传的文件
 * @returns {Promise<boolean>} 是否通过校验
 */
const beforeUpload = async (file) => {
	// 校验文件类型
	const fileTypeList = props.accept
		.split(',')
		.map((item) => item.replace('.', ''));
	const fileType = file.name.split('.').pop();

	if (!fileTypeList.includes(fileType)) {
		ElMessage({
			message: `仅支持 ${fileTypeList.join('、')} 格式`,
			type: 'warning',
		});
		return false;
	}

	// 校验文件大小
	if (props.maxSize) {
		const fileSize = file.size / 1024;
		const maxSizeInKB =
			props.sizeUnit === 'MB' ? props.maxSize * 1024 : props.maxSize;
		if (fileSize > maxSizeInKB) {
			ElMessage({
				message: `大小不能超过 ${props.maxSize}${props.sizeUnit}！`,
				type: 'warning',
			});
			return false;
		}
	}

	// 校验图片尺寸
	return new Promise((resolve, reject) => {
		const img = new Image();
		img.src = URL.createObjectURL(file);
		img.onload = () => {
			URL.revokeObjectURL(img.src);
			const { width, height } = img;

			if (!validateImageSize(width, height)) {
				const message =
					props.width && props.height
						? `图片尺寸必须为 ${props.width}x${props.height}`
						: props.width
							? `图片宽度必须为 ${props.width}px`
							: `图片高度必须为 ${props.height}px`;

				ElMessage({
					message,
					type: 'warning',
				});
				reject(false);
				return;
			}
			loading.value = true;
			resolve(true);
		};
		img.onerror = () => {
			URL.revokeObjectURL(img.src);
			ElMessage({
				message: '图片加载失败',
				type: 'error',
			});
			reject(false);
		};
	});
};
let resUpload = ref({});
const importFile = async (file) => {
	let res = await uploadBookImage(file.file);
	resUpload.value = res;
}
/**
 * 上传成功回调
 * @param {Object} response - 服务器响应数据
 * @param {Object} uploadFile - 上传文件对象
 * @param {Array} uploadFiles - 上传文件列表
 */
const handleSuccess = (response, uploadFile, uploadFiles) => {
	loading.value = false;
	fileList.value.push({ url: uploadFile.url });
	emit('success', resUpload.value, uploadFile, uploadFiles);
};

/**
 * 上传失败回调
 * @param {Error} error - 错误信息
 * @param {Object} uploadFile - 上传文件对象
 * @param {Array} uploadFiles - 上传文件列表
 */
const handleError = (error, uploadFile, uploadFiles) => {
	loading.value = false;
	ElMessage({
		message: '上传失败',
		type: 'error',
	});
	emit('error', error, uploadFile, uploadFiles);
};

/**
 * 超出限制回调
 * @param {Array} files - 超出限制的文件列表
 * @param {Array} uploadFiles - 已上传的文件列表
 */
const handleExceed = (files, uploadFiles) => {
	ElMessage({
		message: `最多只能上传 ${props.limit} 张图片`,
		type: 'warning',
	});
	emit('exceed', files, uploadFiles);
};

/**
 * 移除图片
 * @param {Object} file - 要移除的文件对象
 * @param {number} index - 文件索引
 */
const handleRemove = (file, index) => {
	fileList.value.splice(index, 1);
	proUploadImgRef.value.handleRemove(file);
	emit('remove', file);
};
</script>

<style lang="scss">
.pro-upload-img-box {
	.pro-upload-img-content {
		display: flex;
		flex-wrap: wrap;

		// 上传组件样式
		.pro-upload-img {
			/*display: flex;
			flex-wrap: wrap;*/
			width: 100%;

			// 已上传图片卡片样式
			.upload-img-card {
				width: 100px;
				height: 100px;
				position: relative;
				/*margin: 0 12px 12px 0;*/
				// 图片样式
				.img-sty {
					width: 100%;
					height: 100%;
					overflow: hidden;
					border-radius: 6px;
				}
				// 删除按钮样式
				.img-close {
					position: absolute;
					right: -6px;
					top: -6px;
					width: 20px;
					height: 20px;
					cursor: pointer;
					z-index: 2;
				}
				// 遮罩层样式
				.img-mask {
					background: rgba(0, 0, 0, 0.3);
					border-radius: 6px;
					position: absolute;
					top: 0;
					left: 0;
					width: 100%;
					height: 100%;
					pointer-events: none;

					.img-preview {
						position: absolute;
						right: 8px;
						bottom: 8px;
						width: 20px;
						height: 20px;
						pointer-events: none;
					}
				}
			}

			// 上传按钮样式
			.upload-card {
				width: 100px;
				height: 100px;
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: center;
				border: 1px dashed #d9d9d9;
				border-radius: 6px;
				/*margin: 0 12px 12px 0;*/

				.upload-icon {
					font-size: 20px;
					color: #8c939d;
					text-align: center;
					line-height: 1;
				}

				.upload-text {
					line-height: 24px;
					color: #8c939d;
					font-size: 14px;
					text-align: center;
					margin-top: 10px;
				}
			}
		}

		// 禁用状态样式
		.is-disabled {
			:deep(.el-upload--picture-card) {
				cursor: not-allowed;
			}
			.upload-card {
				cursor: not-allowed;
				opacity: 0.6;
			}
		}

		// 上传组件样式覆盖
		:deep(.el-upload--picture-card) {
			width: 100px;
			height: 100px;
			background-color: #fff;
			/*margin: 0 12px 12px 0;*/
		}
		:deep(.el-upload-list__item) {
			width: auto;
			height: auto;
			overflow: visible;
		}
	}
	// 提示文字样式
	.upload-tip {
		font-size: 12px;
		color: #909399;
	}
}
</style>
